@@ -0,0 +1,51 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from __future__ import division |
|
| 4 |
+ |
|
| 5 |
+import random |
|
| 6 |
+ |
|
| 7 |
+from utils.algorithm.b64 import b64_decrypt, b64_encrypt |
|
| 8 |
+from utils.algorithm.rsalg import rsa_decrypt, rsa_encrypt |
|
| 9 |
+from utils.error.response_utils import response |
|
| 10 |
+ |
|
| 11 |
+ |
|
| 12 |
+CIPHER_ALGORITHM = ('B64', 'RSA')
|
|
| 13 |
+ |
|
| 14 |
+CIPHER_PREFIX = {
|
|
| 15 |
+ 'B64': 'alg1', |
|
| 16 |
+ 'RSA': 'alg2', |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+ |
|
| 20 |
+def encrypt(request): |
|
| 21 |
+ plaintext = request.POST.get('plaintext', '')
|
|
| 22 |
+ |
|
| 23 |
+ alg = random.choice(CIPHER_ALGORITHM) |
|
| 24 |
+ |
|
| 25 |
+ if alg == 'B64': |
|
| 26 |
+ ciphertext = b64_encrypt(plaintext) |
|
| 27 |
+ elif alg == 'RSA': |
|
| 28 |
+ ciphertext = rsa_encrypt(plaintext) |
|
| 29 |
+ else: |
|
| 30 |
+ ciphertext = plaintext |
|
| 31 |
+ |
|
| 32 |
+ return response(200, data={
|
|
| 33 |
+ 'ciphertext': u'%s+%s' % (CIPHER_PREFIX.get(alg, ''), ciphertext), |
|
| 34 |
+ }) |
|
| 35 |
+ |
|
| 36 |
+ |
|
| 37 |
+def decrypt(request): |
|
| 38 |
+ ciphertext = request.POST.get('ciphertext', '')
|
|
| 39 |
+ |
|
| 40 |
+ alg, ciphertext = ciphertext.split('+', 1)
|
|
| 41 |
+ |
|
| 42 |
+ if alg == CIPHER_PREFIX['B64']: |
|
| 43 |
+ plaintext = b64_decrypt(ciphertext) |
|
| 44 |
+ elif alg == CIPHER_PREFIX['RSA']: |
|
| 45 |
+ plaintext = rsa_decrypt(ciphertext) |
|
| 46 |
+ else: |
|
| 47 |
+ plaintext = ciphertext |
|
| 48 |
+ |
|
| 49 |
+ return response(200, data={
|
|
| 50 |
+ 'plaintext': plaintext, |
|
| 51 |
+ }) |
@@ -0,0 +1,33 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from __future__ import division |
|
| 4 |
+ |
|
| 5 |
+from mch.models import BrandInfo, DistributorInfo, ModelInfo |
|
| 6 |
+from utils.error.response_utils import response |
|
| 7 |
+ |
|
| 8 |
+ |
|
| 9 |
+def brands_list(request): |
|
| 10 |
+ brands = BrandInfo.objects.filter(status=True) |
|
| 11 |
+ brands = [brand.data for brand in brands] |
|
| 12 |
+ |
|
| 13 |
+ return response(200, data={
|
|
| 14 |
+ 'brands': brands, |
|
| 15 |
+ }) |
|
| 16 |
+ |
|
| 17 |
+ |
|
| 18 |
+def models_list(request): |
|
| 19 |
+ models = ModelInfo.objects.filter(status=True) |
|
| 20 |
+ models = [model.data for model in models] |
|
| 21 |
+ |
|
| 22 |
+ return response(200, data={
|
|
| 23 |
+ 'models': models, |
|
| 24 |
+ }) |
|
| 25 |
+ |
|
| 26 |
+ |
|
| 27 |
+def distributors_list(request): |
|
| 28 |
+ distributors = DistributorInfo.objects.filter(status=True) |
|
| 29 |
+ distributors = [distributor.data for distributor in distributors] |
|
| 30 |
+ |
|
| 31 |
+ return response(200, data={
|
|
| 32 |
+ 'distributors': distributors, |
|
| 33 |
+ }) |
@@ -4,6 +4,7 @@ from django.conf.urls import url |
||
| 4 | 4 |
|
| 5 | 5 |
from account import views as account_views |
| 6 | 6 |
from account import tourguide_views |
| 7 |
+from api import encrypt_views, mch_views |
|
| 7 | 8 |
from box import views as box_views |
| 8 | 9 |
from geo import views as geo_views |
| 9 | 10 |
from group import views as group_views |
@@ -181,3 +182,15 @@ urlpatterns += [ |
||
| 181 | 182 |
urlpatterns += [ |
| 182 | 183 |
url(r'^box/loginqr$', box_views.login_qrcode_api, name='login_qrcode_api'), # 二维码登录 |
| 183 | 184 |
] |
| 185 |
+ |
|
| 186 |
+# Kodo |
|
| 187 |
+urlpatterns += [ |
|
| 188 |
+ url(r'^brands$', mch_views.brands_list, name='brands_list'), |
|
| 189 |
+ url(r'^models$', mch_views.models_list, name='models_list'), |
|
| 190 |
+ url(r'^distributors$', mch_views.distributors_list, name='distributors_list'), |
|
| 191 |
+] |
|
| 192 |
+ |
|
| 193 |
+urlpatterns += [ |
|
| 194 |
+ url(r'^encrypt$', encrypt_views.encrypt, name='encrypt'), |
|
| 195 |
+ url(r'^decrypt$', encrypt_views.decrypt, name='decrypt'), |
|
| 196 |
+] |
@@ -0,0 +1,22 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.contrib import admin |
|
| 4 |
+ |
|
| 5 |
+from mch.models import BrandInfo, DistributorInfo, ModelInfo |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class BrandInfoAdmin(admin.ModelAdmin): |
|
| 9 |
+ list_display = ('brand_id', 'brand_name', 'brand_descr', 'position', 'status', 'created_at', 'updated_at')
|
|
| 10 |
+ |
|
| 11 |
+ |
|
| 12 |
+class ModelInfoAdmin(admin.ModelAdmin): |
|
| 13 |
+ list_display = ('model_id', 'model_name', 'model_descr', 'position', 'status', 'created_at', 'updated_at')
|
|
| 14 |
+ |
|
| 15 |
+ |
|
| 16 |
+class DistributorInfoAdmin(admin.ModelAdmin): |
|
| 17 |
+ list_display = ('distributor_id', 'distributor_name', 'distributor_descr', 'position', 'status', 'created_at', 'updated_at')
|
|
| 18 |
+ |
|
| 19 |
+ |
|
| 20 |
+admin.site.register(BrandInfo, BrandInfoAdmin) |
|
| 21 |
+admin.site.register(ModelInfo, ModelInfoAdmin) |
|
| 22 |
+admin.site.register(DistributorInfo, DistributorInfoAdmin) |
@@ -0,0 +1,8 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.apps import AppConfig |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class MchConfig(AppConfig): |
|
| 8 |
+ name = 'mch' |
@@ -0,0 +1,68 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.3 on 2017-12-30 13:37 |
|
| 3 |
+from __future__ import unicode_literals |
|
| 4 |
+ |
|
| 5 |
+from django.db import migrations, models |
|
| 6 |
+import shortuuidfield.fields |
|
| 7 |
+ |
|
| 8 |
+ |
|
| 9 |
+class Migration(migrations.Migration): |
|
| 10 |
+ |
|
| 11 |
+ initial = True |
|
| 12 |
+ |
|
| 13 |
+ dependencies = [ |
|
| 14 |
+ ] |
|
| 15 |
+ |
|
| 16 |
+ operations = [ |
|
| 17 |
+ migrations.CreateModel( |
|
| 18 |
+ name='BrandInfo', |
|
| 19 |
+ fields=[ |
|
| 20 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 21 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
|
|
| 22 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 23 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 24 |
+ ('brand_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)),
|
|
| 25 |
+ ('brand_name', models.CharField(blank=True, help_text='\u54c1\u724c\u540d\u79f0', max_length=255, null=True, verbose_name='brand_name')),
|
|
| 26 |
+ ('brand_descr', models.TextField(blank=True, help_text='\u54c1\u724c\u63cf\u8ff0', max_length=255, null=True, verbose_name='brand_descr')),
|
|
| 27 |
+ ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')),
|
|
| 28 |
+ ], |
|
| 29 |
+ options={
|
|
| 30 |
+ 'verbose_name': '\u54c1\u724c\u4fe1\u606f', |
|
| 31 |
+ 'verbose_name_plural': '\u54c1\u724c\u4fe1\u606f', |
|
| 32 |
+ }, |
|
| 33 |
+ ), |
|
| 34 |
+ migrations.CreateModel( |
|
| 35 |
+ name='DistributorInfo', |
|
| 36 |
+ fields=[ |
|
| 37 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 38 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
|
|
| 39 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 40 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 41 |
+ ('distributor_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)),
|
|
| 42 |
+ ('distributor_name', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='distributor_name')),
|
|
| 43 |
+ ('distributor_descr', models.TextField(blank=True, help_text='\u7ecf\u9500\u5546\u63cf\u8ff0', max_length=255, null=True, verbose_name='distributor_descr')),
|
|
| 44 |
+ ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')),
|
|
| 45 |
+ ], |
|
| 46 |
+ options={
|
|
| 47 |
+ 'verbose_name': '\u7ecf\u9500\u5546\u4fe1\u606f', |
|
| 48 |
+ 'verbose_name_plural': '\u7ecf\u9500\u5546\u4fe1\u606f', |
|
| 49 |
+ }, |
|
| 50 |
+ ), |
|
| 51 |
+ migrations.CreateModel( |
|
| 52 |
+ name='ModelInfo', |
|
| 53 |
+ fields=[ |
|
| 54 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 55 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
|
|
| 56 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 57 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 58 |
+ ('model_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)),
|
|
| 59 |
+ ('model_name', models.CharField(blank=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=255, null=True, verbose_name='model_name')),
|
|
| 60 |
+ ('model_descr', models.TextField(blank=True, help_text='\u578b\u53f7\u63cf\u8ff0', max_length=255, null=True, verbose_name='model_descr')),
|
|
| 61 |
+ ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')),
|
|
| 62 |
+ ], |
|
| 63 |
+ options={
|
|
| 64 |
+ 'verbose_name': '\u578b\u53f7\u4fe1\u606f', |
|
| 65 |
+ 'verbose_name_plural': '\u578b\u53f7\u4fe1\u606f', |
|
| 66 |
+ }, |
|
| 67 |
+ ), |
|
| 68 |
+ ] |
@@ -0,0 +1,75 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.db import models |
|
| 4 |
+from django.utils.translation import ugettext_lazy as _ |
|
| 5 |
+from models_ext import BaseModelMixin |
|
| 6 |
+from shortuuidfield import ShortUUIDField |
|
| 7 |
+ |
|
| 8 |
+ |
|
| 9 |
+class BrandInfo(BaseModelMixin): |
|
| 10 |
+ brand_id = ShortUUIDField(_(u'brand_id'), max_length=32, help_text=u'品牌唯一标识', db_index=True, unique=True) |
|
| 11 |
+ brand_name = models.CharField(_(u'brand_name'), max_length=255, blank=True, null=True, help_text=u'品牌名称') |
|
| 12 |
+ brand_descr = models.TextField(_(u'brand_descr'), max_length=255, blank=True, null=True, help_text=u'品牌描述') |
|
| 13 |
+ |
|
| 14 |
+ position = models.IntegerField(_(u'position'), default=1, help_text=u'排序') |
|
| 15 |
+ |
|
| 16 |
+ class Meta: |
|
| 17 |
+ verbose_name = _(u'品牌信息') |
|
| 18 |
+ verbose_name_plural = _(u'品牌信息') |
|
| 19 |
+ |
|
| 20 |
+ def __unicode__(self): |
|
| 21 |
+ return unicode(self.pk) |
|
| 22 |
+ |
|
| 23 |
+ @property |
|
| 24 |
+ def data(self): |
|
| 25 |
+ return {
|
|
| 26 |
+ 'brand_id': self.brand_id, |
|
| 27 |
+ 'brand_name': self.brand_name, |
|
| 28 |
+ 'brand_descr': self.brand_descr, |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
+ |
|
| 32 |
+class ModelInfo(BaseModelMixin): |
|
| 33 |
+ model_id = ShortUUIDField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True, unique=True) |
|
| 34 |
+ model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称') |
|
| 35 |
+ model_descr = models.TextField(_(u'model_descr'), max_length=255, blank=True, null=True, help_text=u'型号描述') |
|
| 36 |
+ |
|
| 37 |
+ position = models.IntegerField(_(u'position'), default=1, help_text=u'排序') |
|
| 38 |
+ |
|
| 39 |
+ class Meta: |
|
| 40 |
+ verbose_name = _(u'型号信息') |
|
| 41 |
+ verbose_name_plural = _(u'型号信息') |
|
| 42 |
+ |
|
| 43 |
+ def __unicode__(self): |
|
| 44 |
+ return unicode(self.pk) |
|
| 45 |
+ |
|
| 46 |
+ @property |
|
| 47 |
+ def data(self): |
|
| 48 |
+ return {
|
|
| 49 |
+ 'model_id': self.model_id, |
|
| 50 |
+ 'model_name': self.model_name, |
|
| 51 |
+ 'model_descr': self.model_descr, |
|
| 52 |
+ } |
|
| 53 |
+ |
|
| 54 |
+ |
|
| 55 |
+class DistributorInfo(BaseModelMixin): |
|
| 56 |
+ distributor_id = ShortUUIDField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True, unique=True) |
|
| 57 |
+ distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称') |
|
| 58 |
+ distributor_descr = models.TextField(_(u'distributor_descr'), max_length=255, blank=True, null=True, help_text=u'经销商描述') |
|
| 59 |
+ |
|
| 60 |
+ position = models.IntegerField(_(u'position'), default=1, help_text=u'排序') |
|
| 61 |
+ |
|
| 62 |
+ class Meta: |
|
| 63 |
+ verbose_name = _(u'经销商信息') |
|
| 64 |
+ verbose_name_plural = _(u'经销商信息') |
|
| 65 |
+ |
|
| 66 |
+ def __unicode__(self): |
|
| 67 |
+ return unicode(self.pk) |
|
| 68 |
+ |
|
| 69 |
+ @property |
|
| 70 |
+ def data(self): |
|
| 71 |
+ return {
|
|
| 72 |
+ 'distributor_id': self.distributor_id, |
|
| 73 |
+ 'distributor_name': self.distributor_name, |
|
| 74 |
+ 'distributor_descr': self.distributor_descr, |
|
| 75 |
+ } |
@@ -0,0 +1,7 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.test import TestCase |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+# Create your tests here. |
@@ -0,0 +1,7 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.shortcuts import render |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+# Create your views here. |
@@ -46,10 +46,12 @@ INSTALLED_APPS = ( |
||
| 46 | 46 |
'django_rlog', |
| 47 | 47 |
'django_uniapi', |
| 48 | 48 |
'django_we', |
| 49 |
+ 'djadmin', |
|
| 49 | 50 |
'api', |
| 50 | 51 |
'account', |
| 51 | 52 |
'box', |
| 52 | 53 |
'group', |
| 54 |
+ 'mch', |
|
| 53 | 55 |
'message', |
| 54 | 56 |
'miniapp', |
| 55 | 57 |
'operation', |
@@ -6,6 +6,7 @@ Pillow==4.3.0 |
||
| 6 | 6 |
StatusCode==1.0.0 |
| 7 | 7 |
TimeConvert==1.4.1 |
| 8 | 8 |
cryptography==1.5.2 |
| 9 |
+django-admin==1.1.0 |
|
| 9 | 10 |
django-curtail-uuid==1.0.0 |
| 10 | 11 |
django-detect==1.0.5 |
| 11 | 12 |
django-file-md5==1.0.1 |
@@ -20,7 +21,7 @@ django-rlog==1.0.7 |
||
| 20 | 21 |
django-shortuuidfield==0.1.3 |
| 21 | 22 |
django-six==1.0.4 |
| 22 | 23 |
django-uniapi==1.0.0 |
| 23 |
-django-we==1.0.16 |
|
| 24 |
+django-we==1.1.2 |
|
| 24 | 25 |
djangorestframework==3.7.2 |
| 25 | 26 |
furl==1.0.1 |
| 26 | 27 |
hiredis==0.2.0 |
@@ -38,7 +39,7 @@ pywe-sign==1.0.6 |
||
| 38 | 39 |
pywe-xml==1.0.0 |
| 39 | 40 |
qiniu==7.1.9 |
| 40 | 41 |
redis==2.10.6 |
| 41 |
-redis-extensions==1.1.3 |
|
| 42 |
+redis-extensions==1.1.6 |
|
| 42 | 43 |
requests==2.18.4 |
| 43 | 44 |
rlog==0.3 |
| 44 | 45 |
shortuuid==0.5.0 |
@@ -0,0 +1,13 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+import base64 |
|
| 4 |
+ |
|
| 5 |
+from CodeConvert import CodeConvert as cc |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+def b64_encrypt(plaintext): |
|
| 9 |
+ return base64.urlsafe_b64encode(cc.Convert2Utf8(plaintext)) |
|
| 10 |
+ |
|
| 11 |
+ |
|
| 12 |
+def b64_decrypt(ciphertext): |
|
| 13 |
+ return cc.Convert2Unicode(base64.urlsafe_b64decode(cc.Convert2Utf8(ciphertext))) |
@@ -0,0 +1,18 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+import base64 |
|
| 4 |
+ |
|
| 5 |
+import rsa |
|
| 6 |
+from CodeConvert import CodeConvert as cc |
|
| 7 |
+ |
|
| 8 |
+ |
|
| 9 |
+pubkey = rsa.PublicKey(7733936986002684982484845608354489436048239676995253266549456282870195715569430535348099548536388503919509506510435040149560886821029985877148893951171111, 65537) |
|
| 10 |
+privkey = rsa.PrivateKey(7733936986002684982484845608354489436048239676995253266549456282870195715569430535348099548536388503919509506510435040149560886821029985877148893951171111, 65537, 316971401565576878144472516350155768882090601834219605321449556369521730928872332388800749109622843453327077688969025635980606763507018292148749534091473, 4517492317789178911663214752269837474466539823144998211438927363654134055916886851, 1711997816918835594017245862832442114582648667392542139046338517030653261) |
|
| 11 |
+ |
|
| 12 |
+ |
|
| 13 |
+def rsa_encrypt(plaintext): |
|
| 14 |
+ return base64.urlsafe_b64encode(rsa.encrypt(cc.Convert2Utf8(plaintext), pubkey)) |
|
| 15 |
+ |
|
| 16 |
+ |
|
| 17 |
+def rsa_decrypt(ciphertext): |
|
| 18 |
+ return rsa.decrypt(base64.urlsafe_b64decode(cc.Convert2Utf8(ciphertext)), privkey) |